/**
 * @Author: hogan
 * @Date: 2021/6/22
 * @General Documentation:
 **/
package config

import (
	"cn.hogan/modetest/src/logger"
	"fmt"
	"gopkg.in/gcfg.v1"
	"os"
	"time"
)

// 配置结构
type Spdider struct {
	UrlListFile     string
	OutputDirectory string
	MaxDepth        int
	CrawlInterval   int
	CrawlTimeout    int
	TargetUrl       string
	ThreadCount     int
}

// 嵌套结构体分开声明，用起来更灵活
type SpiderCfg struct {
	Spider Spdider
}

type ReturnConfig struct {
	// 返回值结构体
	Config Spdider
	Err    error
}

func InitConfig(root string) ReturnConfig {
	/**
	 * @Description:初始化配置文件
	 * @Param:root 加载配置文件路径
	 * @Returns:Spdider{}
	 **/
	var (
		spider SpiderCfg
		res    ReturnConfig
	)

	err := gcfg.ReadFileInto(&spider, root)
	// 将文件加载结构输入到返回值结构体中，做统一返回
	res.Config = spider.Spider
	err = checkConf(res)
	if err != nil {
		time.Sleep(time.Second * 5)
		os.Exit(1)
	}
	res.Err = err
	// 配置加载失败
	if err != nil {
		fmt.Printf("err read config file faild %s", root) // 输出错误给用户提示
		logger.Error("err read config file fail:", root)  // 将错误记录到日志中
	} else {
		// 配置加载成功
		logger.Info("The configuration file was loaded successfully")
	}
	// 返回结果
	return res
}

func checkConf(sp ReturnConfig) error {
	conf := sp.Config

	if conf.UrlListFile == "" {
		return fmt.Errorf("conf -> parameter:UrlListFile err:The file path cannot be empty")
	}
	if conf.OutputDirectory == "" {
		return fmt.Errorf("conf -> parameter:OutputDirectory err:The output path cannot be empty")
	}
	if conf.MaxDepth < 0 {
		return fmt.Errorf("conf -> parameter:MaxDepth err:The crawling depth must not be less than 0")
	}
	if conf.CrawlInterval == 0 {
		return fmt.Errorf("conf -> parameter:CrawlInterval err: Incorrect grasping depth")
	}
	if conf.CrawlTimeout <= 0 {
		return fmt.Errorf("conf -> parameter:CrawlTimeout err: The timeout time is incorrect ")
	}
	if conf.TargetUrl == "" {
		return fmt.Errorf("conf -> parameter:CrawlTimeout err: URL pattern err")
	}
	if conf.ThreadCount == 0 {
		return fmt.Errorf("conf -> parameter:CrawlTimeout err:  ThreadCount err,is not %d", conf.ThreadCount)
	}
	return nil
}
